import { createElement, createRender, onDestroy } from "../../lib/skeleton/index.js";
import { toHref } from "../../lib/skeleton/router.js";
import rxjs, { effect, onLoad, onClick } from "../../lib/rx.js";
import { animate } from "../../lib/animate.js";
import { extname } from "../../lib/path.js";
import { loadCSS } from "../../helpers/loader.js";
import { qs } from "../../lib/dom.js";
import { createLoader } from "../../components/loader.js";
import notification from "../../components/notification.js";
import t from "../../locales/index.js";
import ctrlError from "../ctrl_error.js";
import { Chromecast } from "../../model/chromecast.js";

import { transition, getFilename, getDownloadUrl } from "./common.js";

import componentMetadata, { init as initMetadata } from "./application_image_metadata.js";
import componentPager, { init as initPager } from "./component_pager.js";

import { renderMenubar, buttonDownload, buttonFullscreen } from "./component_menubar.js";

export default function(render) {
    const $page = createElement(`
        <div class="component_imageviewer">
            <component-menubar></component-menubar>
            <div class="component_image_container">
                <div class="images_wrapper">
                    <img class="photo idle hidden" src="${getDownloadUrl()}&size=${window.innerWidth}">
                </div>
                <div class="images_aside scroll-y"></div>
                <div class="component_pager hidden"></div>
            </div>
        </div>
    `);
    render($page);
    transition(qs($page, ".component_image_container"));

    const $imgContainer = qs($page, ".images_wrapper");
    const $photo = qs($page, "img.photo");
    const removeLoader = createLoader($imgContainer);
    const load$ = new rxjs.BehaviorSubject(null);
    const toggleInfo = () => {
        qs($page, ".images_aside").classList.toggle("open");
        componentMetadata(createRender(qs($page, ".images_aside")), { toggle: toggleInfo, load$ });
    };

    renderMenubar(
        qs($page, "component-menubar"),
        buttonDownload(getFilename(), getDownloadUrl()),
        buttonFullscreen(qs($page, ".component_image_container")),
        buttonInfo({ toggle: toggleInfo }),
        buttonChromecast(getFilename(), getDownloadUrl()),
    );

    effect(onLoad($photo).pipe(
        rxjs.tap(() => {
            load$.next($photo);
        }),
        removeLoader,
        rxjs.tap(() => animate($photo, {
            onEnter: () => $photo.classList.remove("hidden"),
            time: 300,
            easing: "cubic-bezier(.51,.92,.24,1.15)",
            keyframes: [
                { opacity: 0, transform: "scale(.97)" },
                { opacity: 1 },
                { opacity: 1, transform: "scale(1)" },
            ],
        })),
        rxjs.catchError((err) => {
            if (err.target instanceof HTMLElement && err.type === "error") {
                return rxjs.of($photo).pipe(
                    removeLoader,
                    rxjs.tap(($img) => {
                        $img.setAttribute("src", "");
                        $img.classList.remove("hidden");
                        $img.classList.add("error");
                        $img.parentElement.appendChild(createElement(`
                            <div class="error no-select">
                                ${t("Not Supported")}
                            </div>
                        `));
                    }),
                    rxjs.catchError(ctrlError()),
                );
            }
            return ctrlError()(err);
        }),
    ));

    componentPager(createRender(qs($page, ".component_pager")));
}

export function init() {
    return Promise.all([
        loadCSS(import.meta.url, "./application_image.css"),
        initPager(), initMetadata(),
    ]);
}

function buttonInfo({ toggle }) {
    const $el = createElement(`
        <span>
            <img class="component_icon" draggable="false" src="" alt="info">
        </span>
    `);
    effect(rxjs.merge(
        onClick($el),
        rxjs.fromEvent(window, "keydown").pipe(rxjs.filter((e) => e.key === "i")),
    ).pipe(rxjs.tap(toggle)));
    return $el;
}

function buttonChromecast(filename, downloadURL) {
    const context = Chromecast.context();
    if (!context) return;

    const chromecastSetup = (event) => {
        switch (event.sessionState) {
        case window.cast.framework.SessionState.SESSION_STARTED:
            chromecastLoader();
            break;
        }
    };
    const chromecastLoader = () => {
        const session = Chromecast.session();
        if (!session) return;

        const link = Chromecast.createLink("/" + toHref(downloadURL));
        const media = new window.chrome.cast.media.MediaInfo(
            link,
            window.CONFIG.mime[extname(filename)],
        );
        media.metadata = new window.chrome.cast.media.PhotoMediaMetadata();
        media.metadata.title = filename;
        media.metadata.images = [
            new window.chrome.cast.Image(location.origin + "/" + toHref("/assets/icons/photo.png")),
        ];
        try {
            const req = Chromecast.createRequest(media);
            session.loadMedia(req);
        } catch (err) {
            console.error(err);
            notification.error(t("Cannot establish a connection"));
        }
    };

    context.addEventListener(
        window.cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
        chromecastSetup,
    );
    onDestroy(() => context.removeEventListener(
        window.cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
        chromecastSetup,
    ));

    const media = Chromecast.media();
    if (media && media.media && media.media.mediaCategory === "IMAGE") chromecastLoader();

    return document.createElement("google-cast-launcher");
}
